/*
 * Flashlib - QB9 common Flash library
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

 
package com.qb9.flashlib.audio
{
	import com.qb9.flashlib.lang.AbstractMethodError;
	
	import flash.display.DisplayObjectContainer;
	import flash.events.Event;
	import flash.events.EventDispatcher;

	/**
	 * Base class of Audio assets (implementing IPlayable) 
	 * 
	 * @see IPlayable
	 * @see Audio
	 */ 

	public class Playable extends EventDispatcher implements IPlayable
	{
		protected var lastPos:Number = 0;
		protected var lastVolume:Number = 1;
		protected var loops:int = 1;
		
		protected var _id:String;
		protected var _playing:Boolean = false;
		protected var _paused:Boolean = false;
		protected var _muted:Boolean = false;

		// ABSTRACT
		
		public function Playable(id:String)
		{
			super(this);
			this._id = id;
		}
		
		// The Event.SOUND_COMPLETE event is propagated
		protected function _onPlayComplete(e:Event) : void
		{
			this.dispatchEvent(e.clone());
		}

		/** @inheritDoc */
		public function get id() : String
		{
			return _id;
		}
		
		/** @inheritDoc */
		public function set id(id:String) : void
		{
			_id = id;
		}
		
		/** @inheritDoc */
		public function get length() : Number
		{
			throw new AbstractMethodError();
		}

		/** @inheritDoc */
		public function get paused() : Boolean
		{
			return _paused;
		}
		
		/** @inheritDoc */
		public function get playing() : Boolean
		{
			return _playing;
		}
		
		/** @inheritDoc */
		public function get muted() : Boolean
		{
			return _muted;
		}
		
		/** @inheritDoc */
		public function get position() : Number
		{
			throw new AbstractMethodError(); 
		}
		
		/** @inheritDoc */
		public function set position(pos:Number) : void
		{
			this.lastPos = pos;
			this.loop(loops);
		}
		
		/** @inheritDoc */
		public function get volume() : Number
		{	
			throw new AbstractMethodError(); 
		}
		
		/** @inheritDoc */
		public function set volume(vol:Number) : void
		{
			if (this._muted)
				this.lastVolume = vol;
		}
		
		/* Public methods */
		
		/** @inheritDoc */
		public function play() : void
		{
			this.loop(1);
		}
		
		/** @inheritDoc */
		public function loop(times:int = int.MAX_VALUE) : void
		{
			if (!this.playing)
			{
				this._playing = true;
				this._paused = false;
				this.loops = times;
			}
		}
		
		/** @inheritDoc */
		public function stop() : void
		{
			this._playing = false;
			this._paused = false;
			this.lastPos = 0;
		}
		
		/** @inheritDoc */
		public function resume() : void
		{
			this._playing = true;
			this._paused = false;			
		}
		
		/** @inheritDoc */
		public function pause() : void
		{
			this._playing = false;
			this._paused = true;			
			this.lastPos = this.position;			
		}
		
		/** @inheritDoc */
		public function mute() : void
		{
			// I set to false so 2 calls to mute don't lose the original volume
			this._muted = false;

			this.lastVolume = this.volume;
			this.volume = 0;
			this._muted = true;
		}
		
		/** @inheritDoc */
		public function unmute() : void
		{
			this._muted = false;
			this.volume = this.lastVolume;
		}
		
		/**
		 * Releases all resources used by the instance.
		 * After this call, the object can no longer be used.
		 */
		public function dispose() : void
		{
			throw new AbstractMethodError();
		}
	}
}
